package com.boby.homecamera.view

import android.content.Context
import android.net.Uri
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.ProgressBar
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import com.alexvas.rtsp.widget.RtspDataListener
import com.alexvas.rtsp.widget.RtspStatusListener
import com.alexvas.rtsp.widget.RtspSurfaceView
import com.alexvas.rtsp.widget.toHexString
import com.boby.homecamera.R
import com.boby.lib_common.util.BLog
import kotlin.math.min
import androidx.core.net.toUri
import androidx.core.view.isVisible
import com.alexvas.rtsp.widget.RtspProcessor
import com.alexvas.rtsp.widget.RtspTextureView

class RtspView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ConstraintLayout(context, attrs) {
    private val vShutterSurface: View
    private val pbLoadingSurface: ProgressBar
    private val svVideoSurface: RtspTextureView
    private val TAG = "RtspView"
    private var svVideoSurfaceResolution = Pair(0, 0)
    private var reConnect = 0
    private var stoped = false
    private val rtspStatusSurfaceListener = object : RtspStatusListener {
        override fun onRtspStatusConnecting() {
            BLog.d(TAG, "onRtspStatusConnecting()")
            pbLoadingSurface.visibility = View.VISIBLE
            vShutterSurface.visibility = View.VISIBLE
        }

        override fun onRtspStatusConnected() {
            BLog.d(TAG, "onRtspStatusConnected()")
            keepScreenOn = true
        }

        override fun onRtspStatusDisconnecting() {
            BLog.d(TAG, "onRtspStatusDisconnecting()")
            // todo show error or refresh

        }

        override fun onRtspStatusDisconnected() {
            BLog.d(TAG, "onRtspStatusDisconnected()")
            // todo show error or refresh
            pbLoadingSurface.visibility = View.GONE
            vShutterSurface.visibility = View.VISIBLE
            pbLoadingSurface.isEnabled = false
            keepScreenOn = false
            isStart = false
        }

        override fun onRtspStatusFailedUnauthorized() {
            BLog.d(TAG, "onRtspStatusFailedUnauthorized() RTSP username or password invalid")
            onRtspStatusDisconnected()
            pbLoadingSurface.visibility = View.GONE
            isStart = false
        }

        override fun onRtspStatusFailed(message: String?) {
            BLog.d(TAG, "onRtspStatusFailed(message='$message')")
            onRtspStatusDisconnected()
            pbLoadingSurface.visibility = View.GONE
            isStart = false
            if (isVisible) {
                //重连
                reConnect()
            }

        }

        override fun onRtspFirstFrameRendered() {
            BLog.d(TAG, "onRtspFirstFrameRendered()")
            pbLoadingSurface.visibility = View.GONE
            vShutterSurface.visibility = View.GONE
        }

        override fun onRtspFrameSizeChanged(width: Int, height: Int) {
            BLog.d(TAG, "onRtspFrameSizeChanged(width=$width, height=$height)")
            svVideoSurfaceResolution = Pair(width, height)
            ConstraintSet().apply {
                clone(this@RtspView)
                setDimensionRatio(svVideoSurface.id, "$width:$height")
                applyTo(this@RtspView)
            }
        }
    }

    private val rtspDataListener = object : RtspDataListener {
        override fun onRtspDataApplicationDataReceived(
            data: ByteArray,
            offset: Int,
            length: Int,
            timestamp: Long
        ) {
            val numBytesDump = min(length, 25) // dump max 25 bytes
            BLog.d(
                TAG,
                "RTSP app data ($length bytes): ${data.toHexString(offset, offset + numBytesDump)}"
            )
        }
    }

    init {
        LayoutInflater.from(context).inflate(R.layout.view_rtsp, this, true)
        vShutterSurface = findViewById(R.id.vShutterSurface)
        pbLoadingSurface = findViewById(R.id.pbLoadingSurface)
        svVideoSurface = findViewById(R.id.svVideoSurface)
        init()
    }

    private fun init() {
        svVideoSurface.setStatusListener(rtspStatusSurfaceListener)
//        svVideoSurface.setDataListener(rtspDataListener)
    }

    private var rtspUrl: String? = null
    private var userName: String? = null
    private var password: String? = null
    private var isStart = false
    fun start(rtspUrl: String, userName: String?, password: String?) {
        if(isStart){
            return
        }

        stoped = false
        this.rtspUrl = rtspUrl
        this.userName = userName
        this.password = password
        reConnect = 0
        BLog.d(TAG, "start $rtspUrl")
        svVideoSurface.visibility = View.VISIBLE
        vShutterSurface.visibility = View.VISIBLE
        val uri = rtspUrl.toUri()
        svVideoSurface.apply {
            init(
                uri,
                username = userName ?: "",
                password = password ?: "",
                userAgent = "rtsp-client-android"
            )
            debug = false
            start(
                requestVideo = true,
                requestAudio = true,
                requestApplication = true
            )
        }

    }

    private fun reConnect() {
        if (stoped || reConnect > 3) {
            stoped = true
            return
        }
        reConnect++

        if(rtspUrl.isNullOrEmpty()){
            return
        }

        BLog.d(TAG,"reConnect $reConnect")
        start(rtspUrl?:"",userName,password)
    }

    fun stop() {
        isStart = false
        BLog.d(TAG, "stop")
        stoped = true
//        if (svVideoSurface.isStarted()) {
            svVideoSurface.stop()
//        }
    }




}